package com.witdata.rabbit.producer;

import com.alibaba.fastjson2.JSON;
import com.witdata.common.domain.Status;
import com.witdata.common.exception.GlobalException;
import com.witdata.common.util.IdUtils;
import com.witdata.rabbit.domain.Handle;
import com.witdata.rabbit.domain.HandleStatus;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.*;

@Component
@Data
@Slf4j
public class InstanceProducer {
    private Long serverId;
    private RabbitTemplate rabbitTemplate;
    private Map<Long, HandleStatus> handleStatusMap;

    @Autowired
    public InstanceProducer(RabbitTemplate rabbitTemplate, Map<Long, HandleStatus> handleStatusMap) {
        this.serverId = IdUtils.createId();
        this.rabbitTemplate = rabbitTemplate;
        this.handleStatusMap = handleStatusMap;
    }

    public <T> String send(Long instanceId, Handle handle, T data) throws GlobalException {
        String queueName = "/instance/" + instanceId;
        Long id = IdUtils.createId();
        HandleStatus handleStatus = HandleStatus.builder()
                .id(id)
                .recv("/"+serverId+"/recv")
                .status(HandleStatus.Status.Waiting)
                .handle(handle)
                .build();
        if (!ObjectUtils.isEmpty(data)) {
            handleStatus.setData(JSON.toJSONString(data));
        }
        handleStatusMap.put(id, handleStatus);
        MessageProperties properties = new MessageProperties();
        properties.setExpiration("300000");
        Message message = new Message(JSON.toJSONString(handleStatus).getBytes(), properties);
        rabbitTemplate.send(queueName, message);
        log.trace("发送到队列{}成功！", queueName);
        handleStatus.setData(null);
        synchronized (handleStatus) {
            try {
                handleStatus.wait(30000);
                if (handleStatus.getStatus() == HandleStatus.Status.Waiting) {
                    throw new GlobalException(Status.SERVERERROR);
                }
                handleStatusMap.remove(id);
                return handleStatus.getData();
            } catch (Exception e) {
                throw new GlobalException(Status.SERVERERROR);
            }
        }
    }

    public <T> void syncSend(Long instanceId, Handle handle,T data) {
        HandleStatus handleStatus = HandleStatus.builder()
                .id(IdUtils.createId())
                .recv("/"+serverId+"/recv")
                .handle(handle)
                .data(JSON.toJSONString(data))
                .build();
        String queue = "/instance/" + instanceId;
        log.info("发送消息到队列{}成功！",queue);
        MessageProperties properties = new MessageProperties();
        properties.setExpiration("300000");
        Message message = new Message(JSON.toJSONString(handleStatus).getBytes(), properties);
        rabbitTemplate.send(queue, message);
    }
}
